package model

import (
	"database/sql"
	"errors"
	"math"

	"devOpsApi/common/util"
	"devOpsApi/libs"

	"github.com/jinzhu/gorm"
)

type User struct {
	gorm.Model
	db       *gorm.DB
	UserId   string        `gorm:"column:userId" json:"userId,omitempty" form:"userId" validate:"required"`
	Email    string        `gorm:"column:email" json:"email,omitempty" form:"email" validate:"required"`
	Phone    string        `gorm:"column:phone" json:"phone,omitempty" form:"phone"`
	RealName string        `gorm:"column:realName" json:"realName,omitempty" form:"realName" validate:"required"`
	Form     uint          `gorm:"column:form" json:"form,omitempty" form:"form" validate:"required"`
	Sex      uint          `gorm:"column:sex" json:"sex,omitempty" form:"sex"`
	Status   sql.NullInt64 `gorm:"column:status" json:"status" form:"status"`
	Token    string        `gorm:"-" json:"Token,omitempty"`

	Pwd        string `gorm:"column:pwd" json:"pwd,omitempty" form:"pwd" validate:"required,min=6,max=12"`
	UserSecret string `gorm:"-" json:"UserSecret,omitempty"`

	RoleId   uint   `gorm:"-" json:"roleId"`
	RoleName string `gorm:"-" json:"roleName"`
	RoleNodes   string        `gorm:"-" json:"roleNodes"`
}

func (User) TableName() string {
	return "user"
}

// 创建User初始化函数
func NewUser() *User {
	return &User{db: libs.DB}
}

func (m *User) List(page, pagesize uint) ([]User, uint, uint) {
	db := libs.DB
	var data = []User{}
	var totalCount uint
	limit := pagesize
	offset := (page - 1) * limit
	fields := "uru.role_id,ur.role_name,user.id,user.userId,user.phone,user.email,user.realName,user.form,user.status,user.created_at,user.updated_at,user.deleted_at"
	db.Model(&User{}).Count(&totalCount)
	err := db.Model(&User{}).Select(fields).Joins("left join user_role_user as uru on user.id = uru.user_id").Joins("left join user_role as ur on uru.role_id = ur.id").Offset(offset).Limit(limit).Order("id asc").Find(&data).Error
	if err != nil {
		//log.Fatalln(err)
	}
	totalPages := uint(math.Ceil(float64(totalCount) / float64(limit)))
	return data, totalCount, totalPages
}

// 获取所有用户
func (m *User) GetAllUser() (user []*User) {
	db := libs.DB
	fields := "uru.role_id,ur.role_name,user.id,user.userId,user.phone,user.email,user.realName,user.form,user.status,user.created_at,user.updated_at,user.deleted_at"
	err := db.Model(&User{}).Select(fields).Joins("left join user_role_user as uru on user.id = uru.user_id").Joins("left join user_role as ur on uru.role_id = ur.id").Order("id asc").Find(&user).Error
	if err != nil {
		//log.Fatalln(err)
	}
	return
}

// 获取用户信息
func (m *User) GetUser(id uint) (user User, err error) {
	err = m.db.Where("id = ? ", id).First(&user).Error
	return
}

// 获取用户信息
func (m *User) GetUserByUserId(userId string) (user User, err error) {
	err = m.db.Where("userId = ? ", userId).First(&user).Error
	return
}

// 获取用企业员工id
func (m *User) GetEntIdUsers(entId string) (users []User, err error) {
	err = m.db.Select("id").Where("entId = ? ", entId).Find(&users).Error
	return
}

// 获取用户ID 获取用户组信息
func (m *User) GetUser2Role(id uint) (roleId uint, roleName string) {
	RoleUserModel := NewUserRoleUser()
	roleModel := NewUserRole()
	RoleUser, _ := RoleUserModel.GetUserRole(int(id))
	Role, _ := roleModel.GetRole(uint(RoleUser.RoleId))
	return Role.ID, Role.RoleName
}

// 密码修改
func (m *User) UpdatePwd(user_id uint, pwd string) (err error) {
	var user User
	if m.db.Where("id = ? ", user_id).First(&user).RecordNotFound() {
		err = errors.New("用户不存在")
		return
	}

	if user.Form != 2 {
		return errors.New("该用户不是注册用户,不允许修改密码")
	}

	Md5Pwd := util.BeeMd5(pwd + user.UserSecret)
	err = m.db.Model(&User{}).Where("id = ? ", user_id).Update("pwd", Md5Pwd).Error
	return
}

// 创建账号
func (m *User) Create() (User, error) {
	var user User
	if err := util.Validate(m); err != nil {
		return user, err
	}

	if !m.db.Where("userId = ?", m.UserId).Find(&User{}).RecordNotFound() {
		return user, errors.New("该账号已经存在")
	}

	if !m.db.Where("email = ?", m.Email).Find(&User{}).RecordNotFound() {
		return user, errors.New("该邮箱已经存在")
	}

	m.Pwd = util.BeeMd5(m.Pwd + m.UserSecret)

	if err := m.db.Create(m).Error; err != nil {
		return user, err
	}

	UserRoleUserModel := NewUserRoleUser()
	if err := UserRoleUserModel.CreateDefaultRole(m.ID, 2); err != nil {
		return user, err
	}

	m.db.Last(&user)
	return user, nil
}

// 登录检测
func (m *User) LoginCheck(username, pwd string) (User, error) {
	var user User
	if m.db.Where("userId = ?", username).First(&user).RecordNotFound() {
		return User{}, errors.New("账号不存在")
	}

	if user.Pwd != util.BeeMd5(pwd+user.UserSecret) {
		return User{}, errors.New("密码错误")
	}

	var roleUser UserRoleUser
	if m.db.Model(&UserRoleUser{}).Where("user_id = ?", user.ID).First(&roleUser).RecordNotFound() {
		return User{}, errors.New("用户对应角色关系不存在!")
	}
	user.RoleId = roleUser.RoleId

	var role UserRole
	if m.db.Model(&UserRole{}).Where("id = ?", roleUser.RoleId).First(&role).RecordNotFound() {
		return User{}, errors.New("角色不存在!")
	}
	user.RoleName = role.RoleName
	return user, nil
}

func (m *User) Delete(id uint) error {
	if err := m.db.Where("id=?", id).Delete(&m).Error; err != nil {
		return err
	}
	return nil
}

func (m *User) RealDel(id uint) error {
	if err := m.db.Unscoped().Where("id=?", id).Delete(&m).Error; err != nil {
		return err
	}
	return nil
}

func (m *User) ArrayColumnById(ids []uint) (map[uint]User, error) {
	var users []User
	result := make(map[uint]User, len(ids))

	if notFound := m.db.Model(&User{}).Where("id in (?)", ids).Find(&users).RecordNotFound(); notFound {
		return nil, errors.New("查询用户信息失败")
	}

	for _, v := range users {
		result[v.ID] = v
	}

	return result, nil
}

// 角色操作
type UserRole struct {
	db       *gorm.DB
	ID       uint   `gorm:"column:id" json:"id" form:"id"`
	RoleName string `gorm:"column:role_name" json:"role_name" form:"role_name"`
}

func NewUserRole() *UserRole {
	return &UserRole{db: libs.DB}
}

func (m *UserRole) GetAllRole() (gd *gorm.DB, role []*UserRole) {
	gd = m.db.Order("id ASC").Find(&role)
	return
}

func (m *UserRole) GetRole(id uint) (role UserRole, err error) {
	err = m.db.Where("id = ? ", id).First(&role).Error
	return
}

func (m *UserRole) RoleCreate() error {
	if !m.db.Where("role_name = ?", m.RoleName).Find(&UserRole{}).RecordNotFound() {
		return errors.New("该名称已经存在")
	}
	return m.db.Create(m).Error
}

func (m *UserRole) RoleUpdate() error {
	if !m.db.Where("id != ? and role_name = ?", m.ID, m.RoleName).Find(&UserRole{}).RecordNotFound() {
		return errors.New("该名称已经存在")
	}
	return m.db.Save(m).Error
}

func (m *UserRole) RoleDelete(id int) error {
	return m.db.Where("id = ?", id).Delete(m).Error
}

// 角色-用户 操作
type UserRoleUser struct {
	db     *gorm.DB
	ID     int64 `gorm:"column:id" json:"id" form:"id"`
	RoleId uint  `gorm:"column:role_id" json:"role_id" form:"role_id"`
	UserId uint  `gorm:"column:user_id" json:"user_id" form:"user_id"`
}

func NewUserRoleUser() *UserRoleUser {
	return &UserRoleUser{db: libs.DB}
}

func (m *UserRoleUser) GetUserRole(user_id int) (role UserRoleUser, err error) {
	err = m.db.Where("user_id = ? ", user_id).First(&role).Error
	return
}

func (m *UserRoleUser) CreateDefaultRole(user_id uint, roleId uint) (err error) {
	var user User
	if m.db.Model(&User{}).Where("id = ? ", user_id).First(&user).RecordNotFound() {
		err = errors.New("用户不存在")
		return
	}
	err = m.db.Model(&UserRoleUser{}).Create(&UserRoleUser{UserId: user_id, RoleId: roleId}).Error
	return
}

func (m *UserRoleUser) UpdateRole(user_id, role_id uint) (err error) {
	var userRoleUser UserRoleUser
	var userRole UserRole
	var user User

	if m.db.Model(&UserRole{}).Where("id = ? ", role_id).First(&userRole).RecordNotFound() {
		err = errors.New("角色不存在")
		return
	}

	if m.db.Model(&User{}).Where("id = ? ", user_id).First(&user).RecordNotFound() {
		err = errors.New("用户不存在")
		return
	}

	if m.db.Model(&UserRoleUser{}).Where("user_id = ? ", user_id).First(&userRoleUser).RecordNotFound() {
		err = m.db.Model(&UserRoleUser{}).Create(&UserRoleUser{UserId: user_id, RoleId: role_id}).Error
	} else {
		err = m.db.Model(&UserRoleUser{}).Where("user_id = ? ", user_id).Update("role_id", role_id).Error
	}

	return
}

func (m *UserRoleUser) UpdateStatus(user_id uint, status int) (err error) {
	var user User
	if m.db.Model(&User{}).Where("id = ? ", user_id).First(&user).RecordNotFound() {
		err = errors.New("用户不存在")
		return
	}
	err = m.db.Model(&User{}).Where("id = ? ", user_id).Update("status", sql.NullInt64{Int64: int64(status), Valid: true}).Error
	return
}

func (m *UserRoleUser) RealDel(user_id uint) error {
	if err := m.db.Unscoped().Where("user_id=?", user_id).Delete(&m).Error; err != nil {
		return err
	}
	return nil
}

// 角色-Action 操作
type UserRoleRoute struct {
	db     *gorm.DB
	ID     int64  `gorm:"column:id" json:"id" form:"id"`
	RoleId int64  `gorm:"column:role_id" json:"role_id" form:"role_id"`
	Path   string `gorm:"column:path" json:"path" form:"path"`
}

func NewUserRoleRoute() *UserRoleRoute {
	return &UserRoleRoute{db: libs.DB}
}

func (m *UserRoleRoute) GetAllRoutes(role_id uint) (routes []string, err error) {
	var route []*UserRoleRoute
	err = m.db.Where("role_id = ? ", role_id).Find(&route).Error
	if err == nil {
		for _, v := range route {
			routes = append(routes, v.Path)
		}
	}
	return
}

func (m *UserRoleRoute) RealDel(role_id int) error {
	if err := m.db.Unscoped().Where("role_id=?", role_id).Delete(&m).Error; err != nil {
		return err
	}
	return nil
}

func (m *UserRoleRoute) Add() (err error) {
	err = m.db.Create(m).Error
	return
}

type UserOauth struct {
	gorm.Model
	db           *gorm.DB
	Uid          uint   `gorm:"column:uid" json:"Uid"`
	GitLabUserId uint   `gorm:"column:gitLabUserId" json:"GitLabUserId"`
	GitLabUser   string `gorm:"column:gitLabUser" json:"GitLabUser"`
	GitLabPwd    string `gorm:"column:gitLabPwd" json:"GitLabPwd"`
	GitServer    string `gorm:"-" json:"GitServer"`
}

// 创建User初始化函数
func NewUserOauth() *UserOauth {
	return &UserOauth{db: libs.DB}
}

func (m *UserOauth) Create() (UserOauth, error) {
	var userOauth UserOauth
	if err := m.db.Create(m).Error; err != nil {
		return userOauth, err
	}
	m.db.Last(&userOauth)
	return userOauth, nil
}

func (m *UserOauth) Exists(Uid uint) bool {
	return !m.db.Where("uid = ?", Uid).First(&UserOauth{}).RecordNotFound()
}

func (m *UserOauth) One(Uid uint) (res UserOauth, err error) {
	err = m.db.Where("uid = ?", Uid).First(&res).Error
	return
}

func (m *UserOauth) Update() (err error) {
	db := libs.DB
	err = db.Save(m).Error
	return
}